﻿using LightCAD.Core;

using LightCAD.Runtime;
using SkiaSharp;
using SkiaSharp.Views.Desktop;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;

namespace LightCAD.UI
{
    public partial class MainUIWindow : Form, IMainUI, IMainWindow
    {

        //private DocumentControl docCtrl;
        private bool hasDocument;
        private bool isActive;

        private DocumentRuntime curDocRt;
        private TitleTabItemControl curHeader;
        private StartupPage startupView;
        private TitleTabItemControl startupHeader;

        public event EventHandler<ActiveChangedEventArgs> ActiveChanged;

        public Dictionary<DocumentRuntime, List<IDocumentEidtorControl>> Editors = new Dictionary<DocumentRuntime, List<IDocumentEidtorControl>>();

        public IPropertyControl PropertyForm;

        private bool _showSplash;
        private SplashScreen _splashScreen;

        public MainUIWindow()
        {
            InitializeComponent();
            this.Load += MainUIWindow_Load;
            this.SizeChanged += MainUIWindow_SizeChanged;
            this.Deactivate += MainUIWindow_Deactivate;
            this.Activated += MainUIWindow_Activated;
            this.FormClosing += MainUIWindow_FormClosing;
            AutoScaleMode = AutoScaleMode.Dpi;
            InitTitleBarHandler();
            InitTabMenu();
            InitPropertyForm();
            CommandCenter.CommonCommandExecute += Instance_CommandExecute;
        }

        private void MainUIWindow_FormClosing(object? sender, FormClosingEventArgs e)
        {
            //TODO:关闭前文档存储判断
            //Closing时会从窗口向子元素清理资源，导致GLControl刷新异常
            AppRuntime.IsClosing = true;
        }

        public MainUIWindow(bool hasDocument) : this()
        {
            this.hasDocument = hasDocument;
        }
        private void InitTabMenu()
        {
            TabMenuCreator.WindowHandler = WindowHandler;
            TabMenuCreator.CreateDrawing(this.TabMenu);

            this.TabMenu.ItemClick += TabMenu_ItemClick;

        }

        public void InitPropertyForm()
        {
            var propForm = new PropertyControl2()
            {
                TabText = "属性",
                AutoScaleMode = AutoScaleMode.None,
                CloseButtonVisible = false,
                CloseButton = false
            };

            propForm.Show(dockPanel, DockState.DockLeft);
            this.PropertyForm = propForm;

            dockPanel.ResumeLayout(true);

        }

        private void TabMenu_ItemClick(object? sender, EventArgs e)
        {
            TabButton button = null;
            if (sender is ToolStripMenuItem)
            {
                button = (TabButton)(sender as ToolStripMenuItem).Tag;
            }
            if (sender is RibbonButton)
            {
                button = (sender as RibbonButton).Button;
            }
            if (button.IsCommand)
            {
                var cmdName = button.CommandName;
                if (string.IsNullOrEmpty(cmdName))
                {
                    cmdName = button.Name;
                }
                UIUtils.ExecuteCommand(cmdName);

            }
        }

        public void WindowHandler(object sender, EventArgs e)
        {
            var btn = (sender as RibbonButton).Button;

            var editorType1 = "Drawing";
            var editorType2 = "Model3d";
            if (Editors.TryGetValue(this.curDocRt, out var editors))
            {
                var edtor1 = editors.First((item) => item.Editor.EditorType.ToString() == editorType1) as DockContent;
                var edtor2 = editors.First((item) => item.Editor.EditorType.ToString() == editorType2) as DockContent;

                if (btn.Name == "DrawingModelSideBySide")
                {
                    //edtor1.Show(dockPanel, DockState.Document);
                    edtor2.Show(edtor1.Pane, DockAlignment.Right, 0.5);
                    edtor1.Pane.ActiveContent = edtor1;
                }
                else if (btn.Name == "DrawingModelNormal")
                {
                    //edtor1.Show(dockPanel, DockState.Document);
                    edtor2.Show(edtor1.Pane, null);//before show,null is append
                    edtor1.Pane.ActiveContent = edtor1;
                }
            }
        }


        #region 接口实现
        public Type WinType => this.GetType();

        public bool IsMinimized => (this.Parent as Form).WindowState == FormWindowState.Minimized;

        SKPoint IMainUI.Location => (this.Parent as Form).Location.ToSKPoint();

        public IDocumentEidtorControl DocumentCtrl => null;//this.docCtrl;

        public bool IsActive
        {
            get { return this.isActive; }
            set
            {
                this.isActive = value;
                ActiveChanged?.Invoke(this, new ActiveChangedEventArgs(value));

            }
        }
        private void MainUIWindow_Activated(object? sender, EventArgs e)
        {
            this.isActive = true;

        }

        private void MainUIWindow_Deactivate(object? sender, EventArgs e)
        {
            this.isActive = false;
        }
        #endregion

        #region 标题条窗口处理

        private void InitTitleBarHandler()
        {
            this.Resize += new EventHandler(winResize_Click);
            this.MouseMove += new MouseEventHandler(Form_MouseMove);

            this.lbMin.MouseEnter += new EventHandler(btn_MouseEnter);
            this.lbMin.MouseLeave += new EventHandler(btn_MouseLeave);
            this.lbMin.Click += lbMin_Click;

            this.lbMax.MouseEnter += new EventHandler(btn_MouseEnter);
            this.lbMax.MouseLeave += new EventHandler(btn_MouseLeave);
            this.lbMax.Click += lbMax_Click;

            this.lbClose.MouseEnter += new EventHandler(btn_MouseEnter);
            this.lbClose.Click += lbClose_Click;
            this.lbClose.MouseLeave += new EventHandler(btn_MouseLeave);

            this.titleBar.MouseDoubleClick += titleBar_MouseDoubleClick;
            this.titleBar.MouseDown += titleBar_MouseDown;
            this.titleBar.MouseMove += titleBar_MouseMove;

            this.lbMessage.MouseEnter += new EventHandler(btn_MouseEnter);
            this.lbMessage.Click += lbLayout_Click;
            this.lbMessage.MouseLeave += new EventHandler(btn_MouseLeave);

            this.lbSettings.MouseEnter += new EventHandler(btn_MouseEnter);
            this.lbSettings.Click += lbSettings_Click; ;
            this.lbSettings.MouseLeave += new EventHandler(btn_MouseLeave);

            this.lbUser.MouseEnter += new EventHandler(btn_MouseEnter);
            this.lbUser.Click += lbUser_Click; ;
            this.lbUser.MouseLeave += new EventHandler(btn_MouseLeave);
        }

        private void Form_MouseMove(object sender, MouseEventArgs e)
        {
            //Q3502120
            if (e.Button == MouseButtons.None)
            {
                if (e.Location.X >= this.Width - 5)
                {
                    if (e.Location.Y > this.Height - 5)
                        this.Cursor = Cursors.SizeNWSE;
                    else
                        this.Cursor = Cursors.SizeWE;
                }
                else if (e.Location.Y >= this.Height - 5)
                    this.Cursor = Cursors.SizeNS;
                else
                    this.Cursor = Cursors.Arrow;
            }
            else
            {
                if (this.Cursor == Cursors.SizeNWSE)
                {
                    this.Width = MousePosition.X - this.Left + 1;
                    this.Height = MousePosition.Y - this.Top + 1;
                }
                else if (this.Cursor == Cursors.SizeWE)
                    this.Width = MousePosition.X - this.Left;
                else if (this.Cursor == Cursors.SizeNS)
                    this.Height = MousePosition.Y - this.Top;
            }
        }

        private Point mousePoint = new Point();
        private void titleBar_MouseMove(object sender, MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (e.Button == MouseButtons.Left)
            {
                if (this.WindowState == FormWindowState.Maximized)
                {
                    this.WindowState = FormWindowState.Normal;
                    return;
                }
                this.Top = Control.MousePosition.Y - mousePoint.Y;
                this.Left = Control.MousePosition.X - mousePoint.X;
            }
        }
        private void titleBar_MouseDown(object sender, MouseEventArgs e)
        {
            base.OnMouseDown(e);
            this.mousePoint.X = e.X;
            this.mousePoint.Y = e.Y;
        }
        private void titleBar_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            WindowMax();
        }

        public void WindowMax()
        {
            if (this.WindowState == FormWindowState.Maximized)
            {
                this.WindowState = FormWindowState.Normal;
            }
            else
            {
                this.MaximumSize = new Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height);
                this.WindowState = FormWindowState.Maximized;
            }
            this.Invalidate();
        }
        public void WindowCenter()
        {
            this.Left = (Screen.PrimaryScreen.WorkingArea.Width - this.Width) / 2;
            if (this.Left < 0) this.Left = 0;
            this.Top = (Screen.PrimaryScreen.WorkingArea.Height - this.Height) / 2;
            if (this.Top < 0) this.Top = 0;

        }
        public bool Formmin = false;
        private void lbMin_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;
            Formmin = true;
        }
        private void winResize_Click(object sender, EventArgs e)
        {
            if (Formmin)
            {
                Formmin = false; 
                this.WindowState = FormWindowState.Normal;

            }
   
        }
        private void lbMax_Click(object sender, EventArgs e)
        {
            WindowMax();
        }
        private void lbClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        private void lbLayout_Click(object? sender, EventArgs e)
        {
            lbMessage_Menu.Show(lbMessage, new Point(0, lbMessage.Height), ToolStripDropDownDirection.BelowRight);
        }
        private void lbSettings_Click(object? sender, EventArgs e)
        {
        }

        private void lbUser_Click(object? sender, EventArgs e)
        {
            MessageBox.Show("Hello user.");
        }

        private void btn_MouseEnter(object sender, EventArgs e)
        {
            if (((Label)sender) == lbClose)
                ((Label)sender).BackColor = Color.Tomato;
            else
                ((Label)sender).BackColor = Color.FromArgb(255, 200, 200, 200);

        }
        private void btn_MouseLeave(object sender, EventArgs e)
        {
            ((Label)sender).BackColor = Color.Transparent;
        }
        #endregion

        #region SplashScreen
        public void SetSplashScreen(Action callback)
        {

            _showSplash = true;
            _splashScreen = new SplashScreen();

            ResizeSplash();
            _splashScreen.Visible = true;
            _splashScreen.TopMost = true;

            Timer _timer = new Timer();
            _timer.Tick += (sender, e) =>
            {
                _splashScreen.Visible = false;
                _timer.Enabled = false;
                _showSplash = false;
                callback();
            };
            _timer.Interval = 2000;
            _timer.Enabled = true;
        }

        private void ResizeSplash()
        {
            if (_showSplash)
            {

                var centerXMain = (this.Location.X + this.Width) / 2.0;
                var LocationXSplash = Math.Max(0, centerXMain - (_splashScreen.Width / 2.0));

                var centerYMain = (this.Location.Y + this.Height) / 2.0;
                var LocationYSplash = Math.Max(0, centerYMain - (_splashScreen.Height / 2.0));

                _splashScreen.Location = new Point((int)Math.Round(LocationXSplash), (int)Math.Round(LocationYSplash));
            }
        }

        #endregion
        private void ResetTheme(VisualStudioToolStripExtender.VsVersion version, ThemeBase theme)
        {

            //vsToolStripExtender1.SetStyle(toolBar, version, theme);
            //vsToolStripExtender1.SetStyle(statusBar, version, theme);
        }

        private void Instance_CommandExecute(object sender, CommandExecuteEventArgs e)
        {
            if (!this.IsActive) return;//非活动不接受命令

            if (curDocRt == null) return;



        }
        private void MainUIWindow_Load(object? sender, EventArgs e)
        {
            this.ResetTheme(VisualStudioToolStripExtender.VsVersion.Vs2015, vS2015LightTheme1);


            this.TitleTab.SelectTabClick += TitleTab_SelectTabClick;
            this.TitleTab.CloseTabClick += TitleTab_CloseTabClick;
            this.TitleTab.AddTabClick += TitleTab_AddTabClick;

            startupHeader = TitleTab.AddTab(new TitleTabItem
            {
                Name = "Homepage",
                Text = "主页",
                Closable = false,
                Icon = Properties.Resources.Homepage
            });
            startupHeader.ContextMenuStrip = null;

            startupView = new StartupPage();
            startupView.Dock = DockStyle.Fill;
            this.Controls.Add(startupView);

            App.Current.OnUIInitilized(this);

            if (!this.hasDocument)
            {
                UIUtils.SetTimeout(this, () =>
                {
                    NewDocument();
                }, 500);
            }
        }



        private void TitleTab_AddTabClick(object? sender, EventArgs e)
        {
            var ttea = e as TitleTabEventArgs;
            this.NewDocument(ttea.TabItemControl);
        }

        private void TitleTab_CloseTabClick(object? sender, EventArgs e)
        {
            var arg = e as TitleTabEventArgs;
            CloseDocument();
        }

        private void TitleTab_SelectTabClick(object? sender, EventArgs e)
        {
            var arg = e as TitleTabEventArgs;
            SetHeaderCurrent(arg.TabItemControl);
        }
        private void btnOpenDrawing_Click(object sender, EventArgs e)
        {
            NewDocument();
        }

        public DocumentRuntime OpenDrawingTab(LcDocument doc) => OpenDrawingTab(doc, null);
        public DocumentRuntime OpenDrawingTab(LcDocument doc, TitleTabItemControl newHeader)
        {
            foreach (var editsItem in this.Editors)
            {
                foreach (var item in editsItem.Value)
                {
                    var doccontent = item as DockContent;
                    doccontent.Hide();
                }
            }
            var editorList = new List<IDocumentEidtorControl>();
            dockPanel.SuspendLayout();
            var docRt = DocumentManager.CreateRt(doc, true);

            var drawingWin = new DrawingEditWindow(docRt);
            drawingWin.SetLayOut(doc, doc.Layouts[0]);
            drawingWin.TabText = "绘图*";//加星表示默认
            drawingWin.AutoScaleMode = AutoScaleMode.None;
            drawingWin.CloseButtonVisible = false;
            drawingWin.CloseButton = false;
            drawingWin.Show(dockPanel);
            editorList.Add(drawingWin);

            var model3dWin = new Model3DEditWindow(docRt);
            model3dWin.TabText = "3D模型*";//加星表示默认
            model3dWin.AutoScaleMode = AutoScaleMode.None;
            model3dWin.CloseButton = false;
            model3dWin.CloseButtonVisible = false;
            model3dWin.Show(dockPanel);
            editorList.Add(model3dWin);

            this.Editors.Add(docRt, editorList);

            docRt.Initilize(drawingWin.DrawingEditRt, model3dWin.Model3DEditRt, PropertyForm);

            var text = Path.GetFileName(doc.FilePath);
            var titleTabItem = new TitleTabItem
            {
                Icon = Properties.FileTypeResources.file_dwg24,
                Name = text,
                Text = text,
                Closable = true
            };
            if (newHeader == null)
                newHeader = TitleTab.AddTab(titleTabItem);
            else
            {
                newHeader.TabItem = titleTabItem;
                newHeader.ResetItem();
            }
            newHeader.Tag = docRt;
            SetHeaderCurrent(newHeader);
            DocumentManager.SetCurrent(doc);
            dockPanel.ResumeLayout(true);
            dockPanel.Panes[1].ActiveContent = drawingWin; //第0个现在为PropertyForm
            return docRt;
        }



        public DocumentRuntime NewDocument()
        {
            var drawingName = TitleTab.NewDrawingText();
            var doc = LcDocument.Create();
            doc.FilePath = drawingName;
            var docRt = OpenDrawingTab(doc);
            return docRt;
        }
        private DocumentRuntime NewDocument(TitleTabItemControl newHeader)
        {
            var doc = LcDocument.Create();
            doc.FilePath = newHeader.TabItem.Text;
            var docRt = OpenDrawingTab(doc, newHeader);
            return docRt;

        }
        private void SetHeaderCurrent(TitleTabItemControl tabItemCtrl)
        {
            TitleTab.SelectTab(tabItemCtrl.TabItem);

            if (tabItemCtrl == startupHeader)
            {
                startupView.BringToFront();
            }
            else
            {
                startupView.SendToBack();
            }

            this.curHeader = tabItemCtrl;
            var docRt = tabItemCtrl.Tag as DocumentRuntime;
            if (docRt != curDocRt)
            {
                if (curDocRt != null)
                {
                    curDocRt.SetActive(false);
                }
                if (docRt != null)
                {
                    docRt.SetActive(true);
                    DocumentManager.SetCurrent(docRt.Document);
                    foreach (var editorItems in this.Editors)
                    {
                        var drt = editorItems.Key;
                        var isShow = drt == docRt;
                        foreach (var item in editorItems.Value)
                        {
                            var dc = (item as DockContent);
                            if (isShow)
                            {
                                dc.Show();
                            }
                            else dc.Hide();

                        }
                        if (isShow)
                            (editorItems.Value[0] as DockContent).Show();
                    }
                }
                curDocRt = docRt;
            }
        }

        public async Task<DocumentRuntime> OpenDocument(string filePath = null)
        {
            if (filePath == null)
            {
                var filePaths = await AppRuntime.UISystem.OpenFileDialog();
                if (filePaths == null) return null;
                filePath = filePaths[0];
            }
            string path = Path.GetExtension(filePath);
            LcDocument lcDocument;
            //if (path.ToLower() == ".dwg")
            //{
            //    try
            //    {
            //        lcDocument = LightCAD.ImpExpDwg.DwgReader.Import(filePath);
            //    }
            //    catch (Exception)
            //    {
            //        return null;
            //    }
            //}
            //else
            {
                if (this.InvokeRequired)
                {
                    var tc = new TaskCompletionSource<DocumentRuntime>();
                    this.Invoke((Delegate)(() =>
                    {
                        var doc = DocumentUtils.Load(filePath);
                        var docRt = OpenDrawingTab(doc);
                        tc.SetResult(docRt);
                    }));
                    return await tc.Task;
                }
                else
                {
                    lcDocument = DocumentUtils.Load(filePath);
                }
            }

            var docRt = OpenDrawingTab(lcDocument);
            return docRt;
        }

        private void CloseDocumentAction()
        {
            //this.docCtrl.RemoveDrawing(this.curDocRt);
            var docRt = this.curHeader.Tag as DocumentRuntime;
            this.TitleTab.RemoveTab(this.curHeader.TabItem);
            if (docRt != null)
            {
                this.Editors[docRt].ForEach(e =>
                {
                    (e as DockContent).Hide();
                    (e as DockContent).Close();
                });
                this.Editors.Remove(docRt);
            }
            // var latestDrawing = this.docCtrl.GetLastestDrawing();
            //if (latestDrawing == null)
            //{
            //    this.curDocRt = null;
            //    this.curHeader = null;
            //}

        }

        public void CloseDocument()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(this.CloseDocumentAction);
            }
            else
            {
                this.CloseDocumentAction();
            }
        }


        private void headerCtxMenu_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {

            var name = e.ClickedItem.Name;
            if (name == "mui_CloseFile")
            {
                this.CloseDocument();
            }
            else if (name == "mui_NewWindow")
            {
                var newWinDoc = curDocRt.Document;
                CloseDocument();//会更改curDocRt
                App.Current.CreateMainWindow(newWinDoc);
            }
        }

        private void headerCtxMenu_Opening(object sender, CancelEventArgs e)
        {
            //if (this.docCtrl != null)
            //{
            //    mui_NewWindow.Visible = this.docCtrl.DrawingCount > 1;
            //}
        }

        private void headerCtxMenu_Opened(object sender, EventArgs e)
        {
        }

        private void MainUIWindow_SizeChanged(object sender, EventArgs e)
        {
            //ResizeSplash();
            /// 注释以下代码，是因为此方案会导致整个窗口不停的Paint,导致RibbonButton闪烁
            //this.Refresh();//解决在CreateParams时 最大化时会不刷新主窗体背景的BUG
            //this.titleBar.Refresh();
            //this.TabMenu.Refresh();
        }

   

        /// <summary>
        /// 阻止TitleTabControl在操作时的闪动,但在最大化时会不刷新主窗体背景
        /// </summary>
        //protected override CreateParams CreateParams
        //{
        //    get
        //    {
        //        var cp = base.CreateParams;
        //        cp.ExStyle |= 0x02000000;
        //        return cp;
        //    }
        //}


    }



}
